package net.danielthompson.danray.structures;

/**
 * User: daniel
 * Date: 7/2/13
 * Time: 20:37
 */
public class Tuple {

   private double X;
   private double Y;
   private double Z;

   public Tuple(double X, double Y, double Z) {
      this.setX(X);
      this.setY(Y);
      this.setZ(Z);
   }

   public double Dot(Tuple tuple) {
      return (getX() * tuple.getX() + getY() * tuple.getY() + getZ() * tuple.getZ());
   }

   public static Tuple Plus(Tuple tuple1, Tuple tuple2) {
      return new Tuple(tuple1.getX() + tuple2.getX(), tuple1.getY() + tuple2.getY(), tuple1.getZ() + tuple2.getZ());
   }

   public void Plus(Tuple tuple) {
      X += tuple.getX();
      Y += tuple.getY();
      Z += tuple.getZ();
   }

   public static Tuple Minus(Tuple tuple1, Tuple tuple2) {
      return new Tuple(tuple1.X - tuple2.X, tuple1.Y - tuple2.Y, tuple1.Z - tuple2.Z);
   }

   public void Minus(Tuple tuple) {
      X -= tuple.getX();
      Y -= tuple.getY();
      Z -= tuple.getZ();
   }

   public static Tuple Scale(Tuple tuple, double t) {
      return new Tuple(t * tuple.getX(), t * tuple.getY(), t * tuple.getZ());
   }

   public void Scale(double t) {
      X *= t;
      Y *= t;
      Z *= t;
   }

   public Tuple Cross(Tuple tuple) {
      return new Tuple(
            Y*tuple.getZ() - Z*tuple.getY(),
            Z*tuple.getX() - X*tuple.getZ(),
            X*tuple.getY() - Y*tuple.getX()
      );
   }

   public static Tuple Cross(Tuple tuple1, Tuple tuple2) {
      return new Tuple(
            tuple1.getY() * tuple2.getZ() - tuple1.getZ() * tuple2.getY(),
            tuple1.getZ() * tuple2.getX() - tuple1.getX() * tuple2.getZ(),
            tuple1.getX() * tuple2.getY() - tuple1.getY() * tuple2.getX()
      );
   }

   public void Normalize() {
      double lengthMultiplier = 1.0 / Length();
      Scale(lengthMultiplier);
   }

   public static Tuple Normalize(Tuple tuple) {
      double lengthMultiplier = 1.0 / tuple.Length();
      return new Tuple(tuple.getX() * lengthMultiplier, tuple.getY() * lengthMultiplier, tuple.getZ() * lengthMultiplier);
   }

   public double Length() {
      return Math.sqrt(X * X + Y * Y + Z * Z);
   }

   public double getX() {
      return X;
   }

   public void setX(double x) {
      X = x;
   }

   public double getY() {
      return Y;
   }

   public void setY(double y) {
      Y = y;
   }

   public double getZ() {
      return Z;
   }

   public void setZ(double z) {
      Z = z;
   }

   public boolean equals(Object obj) {
      if (obj == null)
         return false;
      if (obj == this)
         return true;
      if (!(obj instanceof Tuple))
         return false;

      Tuple rhs = (Tuple) obj;
      return (X == rhs.X && Y == rhs.Y && Z == rhs.Z);
   }

   public String toString() {
      return "X " + X + ", Y " + Y + ", Z " + Z;
   }
}
